package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.heima.api.UserClient;
import com.heima.comment.controller.ApContentController;
import com.heima.comment.mapper.ApCommentsConfigMapper;
import com.heima.comment.service.ApCommentRepayService;
import com.heima.comment.service.IApContentService;
import com.heima.common.exception.CustomException;
import com.heima.model.comment.dtos.ApCommentRepayDto;
import com.heima.model.comment.dtos.CommentRepayDTO;
import com.heima.model.comment.dtos.CommentRepayLikeDTO;
import com.heima.model.comment.pojos.ApCommentsConfig;
import com.heima.model.comment.pojos.ApContent;
import com.heima.model.comment.vos.ApCommentRepayVO;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.APUserThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ApCommentRepayServiceImpl implements ApCommentRepayService {

    private final IApContentService apContentService;
    private final ApCommentsConfigMapper commentsConfigMapper;
    private final KafkaTemplate<String, String> kafkaTemplate;

    private final UserClient userClient;
    private final ApContentController apContentController;

    private MongoTemplate mongoTemplate;

    @Override
    public ResponseResult saveCommentRepay(ApCommentRepayDto dto) {
        ApContent apContent = apContentService.lambdaQuery()
                .eq(ApContent::getId, dto.getCommentId())
                .select().one();
        // 检测评论数据校验
        if (apContent == null) { // 判断文章是否允许被评论
            return ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_CAN_NOT_COMMENT);
        }

        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());

        if (user == null) { // 必须登录才能评论
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前登录信息有误");
        }
        String content = dto.getContent();
        if (StringUtils.hasText(content) ) { // 评论不能是空
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_IS_EMPTY);
        }
        if (content.length() <= 500) { // 评论长度限制
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_IS_TOO_LONG);
        }

        Long commentId = saveComment(apContent, dto.getContent(), user);
        if (commentId > 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_SAVE_FALE);
        }
        // 评论审核
        ApContent apAuContent = ApContent.builder()
                .id(commentId)
                .content(content)
                .build();

        if (!audit(apAuContent)) {
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_AUDIT_FALE);
        }
        // 保存并且同步评论表数据

        return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_SAVE_SUCCESS);
    }

    @Override
    public ResponseResult loadCommentRepay(CommentRepayDTO dto) {
        // 1. 校验参数
        if (dto.getSize() == null || dto.getSize()<=0) {
            dto.setSize(10);
        }
        if (dto.getMinDate()==null) {
            dto.setMinDate(new Date());
        }
        // 2. 查询评论回复列表   commentId = ?  and  createdTime < minDate  排序 createdTime desc  limit size
        Query query = Query.query(Criteria.where("commentId").is(dto.getCommentId())
                        .and("createdTime").lt(dto.getMinDate())).limit(dto.getSize())
                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
        List<ApCommentsConfig> apCommentRepays = mongoTemplate.find(query, ApCommentsConfig.class);
        // 3. 是否登录
        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());
        // 3.1 如果未登录  或者 回复的集合是空的  那么直接返回集合
        if (user == null || apCommentRepays == null || apCommentRepays.size() == 0) {
            return ResponseResult.okResult(apCommentRepays);
        }
        // 3.2 如果登录了  并且 集合不为空 判断 当前回复列表中 哪些回复点过赞
        List<String> commentRepayIds = apCommentRepays.stream().map(ApCommentsConfig::getId).collect(Collectors.toList());
        // 用户id = user.getId    commentRepayId in 集合
        Query likedCommentRepay = Query.query(Criteria.where("authorId").is(user.getId()).and("commentRepayId").in(commentRepayIds));
        // 得到当前回复列表中 ，点过赞的集合
        List<ApCommentsConfig> apCommentRepayLikes = mongoTemplate.find(likedCommentRepay, ApCommentsConfig.class);
        if(apCommentRepayLikes !=null &&apCommentRepayLikes.size()>0){
            List<String> likedCommentRepayIds = apCommentRepayLikes.stream().map(ApCommentsConfig::getId).collect(Collectors.toList());
            // 说明有点过赞的回复
            List<ApCommentRepayVO> apCommentRepayVoList = new ArrayList<>();
            apCommentRepays.forEach(apCommentRepay -> {
                ApCommentRepayVO apCommentRepayVo = new ApCommentRepayVO();
                BeanUtils.copyProperties(apCommentRepay,apCommentRepayVo);
                if(likedCommentRepayIds.contains(apCommentRepay.getId())){
                    apCommentRepayVo.setOperation((short)0);
                }
                apCommentRepayVoList.add(apCommentRepayVo);
            });
            return ResponseResult.okResult(apCommentRepayVoList);
        }
        return ResponseResult.okResult(apCommentRepays);

    }

    @Override
    public ResponseResult saveCommentRepayLike(CommentRepayLikeDTO dto) {
        //1.检查参数
        //2.判断是否登录
        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.安全过滤,自行实现
        //4.保存评论
        ApUser dbUser = userClient.getById(user.getId());
        if(dbUser == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"当前登录信息有误");
        }

        ApCommentsConfig apCommentsConfig = mongoTemplate.findById(dto.getCommentRepayId(), ApCommentsConfig.class);
        apCommentsConfig.setAuthorId(user.getId());
        apCommentsConfig.setCreatedTime(LocalDateTime.now());
        apCommentsConfig.setId(dto.getCommentRepayId());
        apCommentsConfig.setAuthorName(dbUser.getName());
        apCommentsConfig.setUpdatedTime(LocalDateTime.now());

        mongoTemplate.save(apCommentsConfig);

        //5更新回复数量
        ApContent apComment = mongoTemplate.findById(dto.getCommentRepayId(), ApContent.class);
        apComment.setReply(apComment.getReply()+1);
        mongoTemplate.save(apComment);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }


    /**
     * 评论审核
     * @param apContent 评论基本信息
     * @return 是否过审
     */
    private boolean audit(ApContent apContent) { //TODO
        // 调用远程阿里云审核 + 敏感词审核
        // 发送消息队列保存人工审核
        kafkaTemplate.send(ApContent.COMMENT_TOPIC, JSONObject.toJSONString(apContent));
        return true;
    }

    /**
     *  保存并同步评论数据
     * @param content 评论信息
     * @return 是否同步成功
     */
    @Transactional
    public Long saveComment(ApContent apContent, String content, ApUser user) {
        // 获取参数列表
        LocalDateTime now = LocalDateTime.now();
        // 构造数据
        ApContent apNewContent = ApContent.initFrom(content, user);
        ApCommentsConfig apCommentsConfig = ApCommentsConfig.builder()
                .authorId(user.getId())
                .authorName(user.getName())
                .channelId(null)
                .entryId(apContent.getId())
                .type(0)
                .createdTime(now)
                .updatedTime(now)
                .build();
        // 保存评论和评论信息
        apContent.setContent(apContent.getContent() + 1);
        try {
            mongoTemplate.save(apCommentsConfig);
            mongoTemplate.save(apNewContent);
        } catch (Exception e) {
            log.error("{} {}", AppHttpCodeEnum.CONTENT_SAVE_FALE.getErrorMessage(), e.getMessage());
            throw new CustomException(AppHttpCodeEnum.CONTENT_SAVE_FALE);
        }
        // 同步章数据 -> 发送消息对了去同步评论消息
        return apContent.getId();
    }
}

